package com.moleq.mgnetwork;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import com.moleq.base.MQConnection;
import com.moleq.fileclinet.FileClinetTask;
import com.moleq.mgnetwork.FolderMonitor.FileChangeCallback;
import com.moleq.network.CommTask;
import com.moleq.network.CommTaskParser;
import com.moleq.network.ConnectHandler;
import com.moleq.network.Constant;
import com.moleq.network.MGFileHander;
import com.moleq.network.RemoteReportHandler;
import com.moleq.network.ReportCallback;
import com.moleq.network.ReportCreator;
import com.moleq.remote.rpt.RemoteReportServer;
import com.moleq.util.ServiceUtil;

public class TransporterService extends Service {
	/**
	 * create handler object as thread pass to postDelayed
	 */

	private Context sharedContext = null;
	private CommTaskParser xmlParser = new CommTaskParser();
	private MgnetworkTool mgposTool = new MgnetworkTool();

	private static final String TAG = "MGService";
	private static final String PROCESSOR_TAG = "processor";
	private static final String TRANSPORTER_TAG = "transporter";
	private static final String ANALYZER_TAG = "analyzer";

	private boolean isRunning = false;

	private Logger logger = Logger.getLogger("ServiceLog");

	private java.util.logging.FileHandler logHandler = null;

	private MGFileHander filehandler = null;
	private FolderMonitor transporter = null;
	private FolderMonitor processor = null;
	private FolderMonitor analyzer = null;
	// private FolderMonitor mInventoryMonitor = null;
	private CommTaskParser parser = new CommTaskParser();
	// private MgnetworkTool dbhelper = new MgnetworkTool();
	private String mInvDBPath = "";
	private ContextManager mContextManager = new ContextManager();
	private FileChangeCallback transporterCallback = new FileChangeCallback() {

		@Override
		public void onProcessFiles(final File[] files) {

			InitFolder();

			String sendToIp = "";

			transporter.pause();
			String fileName ="";
			try {

				for (File file : files) {
					fileName = "" + file.getAbsoluteFile();

					if (fileName.indexOf(".tmp") >= 0 || fileName.indexOf(".temp") >= 0)
						continue;

					if (fileName.indexOf(".xml") < 0)
						continue;

					CommTask task = parser.getCommTasks(fileName);
					sendToIp = task.getIpAddress();

					if (sendToIp != null && !sendToIp.equals("")) {
						if (sendToIp.equals(ServiceUtil.getLocalIpAddress())) {
							boolean succ = false;
							succ = ServiceUtil.Move("" + fileName, Constant.SDCARD_IN_BOX);
							if (!succ) {
								logger.info(TRANSPORTER_TAG + "-> faild to move file.");
							}

						} else {
							List<String> extrafiles = task.getExtraFiles();
							System.out.println(">>>>>>> send file start <<<<<<<<<");
							for (int i = 0; i < extrafiles.size(); i++) {
								filehandler.sendFile(Constant.SDCARD_OUT_BOX + extrafiles.get(i),sendToIp,Constant.FILE_HANDLER_PORT );
								System.out.println(">>send -> " + Constant.SDCARD_OUT_BOX + extrafiles.get(i));
								Thread.sleep(1000);
							}

							System.out.println(">>send -> " + fileName);
							filehandler.sendFile(fileName,sendToIp,Constant.FILE_HANDLER_PORT );
							Thread.sleep(1000);

							System.out.println(">>>>>>> send file end <<<<<<<<<");
						}
					}

				}
				
			} catch (Exception e) {
				// TODO: handle exception
				logger.info(TRANSPORTER_TAG + "-> " + e.toString());
				
				ServiceUtil.Move("" + fileName, Constant.SDCARD_IN_BOX);
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				logger.info(TRANSPORTER_TAG + "-> " + e.toString());
				ServiceUtil.Move("" + fileName, Constant.SDCARD_IN_BOX);
			}
			transporter.play();
		}

		@Override
		public void onLog(String msg) {
			logger.info(TRANSPORTER_TAG + "-> " + msg);

		}
	};

	private FileChangeCallback processorFileCallback = new FileChangeCallback() {

		@Override
		public void onProcessFiles(final File[] files) {
			// TODO Auto-generated method stub
			System.out.println("------------> processor START <------------- ");

			try {
				for (File file : files) {
					String fileName = "" + file.getAbsoluteFile();

					if (fileName.indexOf(".xml") < 0)
						continue;

					System.out.println("do........parser.getCommTasks");
					CommTask task = parser.getCommTasks(fileName);

					if (task.getType().equals(Constant.TYPE_ITY)) {
						if (mInvConn.isConnected()) {
							MgnetworkTool inventoryTool = new MgnetworkTool();
							inventoryTool.opendb(mInvDBPath);
							inventoryTool.run(task);
						}
					} else if(task.getType().equals(Constant.TYPE_REGISTRATION)){
						///////
						//////
						MgnetworkTool keyTool = new MgnetworkTool();
						keyTool.opendb(mPosDBPath);
						keyTool.setMacAddress(mMacAddress);
						keyTool.runRegKey(task);
					}
					else {
						mgposTool.run(task);
					}

					System.out.println("do........... fileProcessor.processCommTask");

					if (file.exists()) {
						file.delete();
					}

					Thread.sleep(1000);

				}

			} catch (Exception e) {
				System.err.println(PROCESSOR_TAG + "-> error 1");
				logger.info(PROCESSOR_TAG + "-> " + e.toString());
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				System.err.println(PROCESSOR_TAG + "-> error 2");
				e.printStackTrace();
				logger.info(PROCESSOR_TAG + "-> " + e.toString());
			}

		}

		@Override
		public void onLog(String msg) {
			logger.info(PROCESSOR_TAG + "-> " + msg);

		}

	};

	private FileChangeCallback analyzerFileCallback = new FileChangeCallback() {


		@Override
		public void onProcessFiles(File[] files) {

			System.out.println("------------> analyzer START <------------- ");
			try {

				for (File file : files) {
					String fileName = "" + file.getAbsoluteFile();

					System.out.println("open file name -> " + fileName);

					if (fileName.indexOf(".tmp")> 0 || fileName.indexOf(".txt") < 0  )
						continue;

					System.out.println("start analyze file name -> " + fileName);

					Log.e("MingTag", "start analyzer files---->" + file.getName());

					if (file.exists()) {

						HashMap<Integer, String> splitMap = ServiceUtil.parseFileName(file.getName());
						Log.e("MingTag", "hash map  ---->" + splitMap);

						// txt to xml
						String strDate = splitMap.get(0);
						String type = "";
						if (splitMap.size() >= 2) {
							type = splitMap.get(1);
						}

						List<String> settings = mgposTool.getIpAddressList();
						if (type.equals(Constant.TYPE_ITY)) {
							settings = mgposTool.getInventoryTerminalIP();
						} else {
							settings = mgposTool.getIpAddressList();
							settings.remove(ServiceUtil.getLocalIpAddress());
						}

						List<String> records = ServiceUtil.getRecords(file.getAbsolutePath());
						List<String> extraFiles = ServiceUtil.getExtraFiles(file.getAbsolutePath());
						
						File newFile = new File(fileName + ".tmp");
						file.renameTo(newFile);

						if (settings.size() > 0){
							
							String fileType = "";
							String fileDate = "";
							String fileFrom = "";
							String xmlFileName = "";

							for (int i = 0; i < settings.size(); i++) {
								fileFrom = String.format(Constant.FILE_NAME_VALUE, settings.get(i).replace(".", "-"));
								fileType = String.format(Constant.FILE_NAME_VALUE, type);
								fileDate = String.format(Constant.FILE_NAME_VALUE, strDate);
								xmlFileName = String.format(Constant.TASK_XML_FILE_NAME, fileFrom + fileType + fileDate);
								
								CommTask task = new CommTask();
								task.setIpAddress(settings.get(i));
								task.setCreateDateTime(new Date().toGMTString());
								task.setType(type);
								task.setDbAction(records);
								task.setExtraFiles(extraFiles);

								for (int j = 0; j < extraFiles.size(); j++) {
									String cacheExtraFileName = Constant.SDCARD_MGPOS_CACHE + extraFiles.get(j);
									ServiceUtil.Move(cacheExtraFileName, Constant.SDCARD_OUT_BOX);
								}

								xmlParser.save(task, Constant.SDCARD_OUT_BOX + xmlFileName);
							}
						}
					
						newFile.delete();
					}
				}
			} catch (Exception e) {
				logger.info(ANALYZER_TAG + "-> " + e.toString());
				System.out.println("-------> error1 -> " + e.toString());
			} catch (Throwable e) {
				System.out.println("-------> error2 -> " + e.getMessage());
				logger.info(ANALYZER_TAG + "-> " + e.toString());
			}

		}

		@Override
		public void onLog(String msg) {
			logger.info(ANALYZER_TAG + "-> " + msg);

		}

	};

	private ReportCallback mReportCallback = new ReportCallback() {

		@Override
		public void onFaild(String msg) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onCreate(String reportData) {
			// TODO Auto-generated method stub

		}
	};

	private ConnectHandler networkMonitor;
	private RemoteReportHandler mReportService;
	private ReportCreator mReportCreator;
	private RemoteReportServer mRemoteRptSvr;

	private void doTaskJob() {

		// connect service
		networkMonitor = new ConnectHandler();
		networkMonitor.start();

		// remote report service
		mReportCreator = new ReportCreator(mPosDBPath);
		mReportService = new RemoteReportHandler();
		mReportService.setReportCreator(mReportCreator, mReportCallback);
		mReportService.start();

		//
		filehandler = new MGFileHander();
		filehandler.setInBox(Constant.SDCARD_IN_BOX);
		filehandler.listen(Constant.FILE_HANDLER_PORT);

		// analyzer
		analyzer = new FolderMonitor(Constant.SDCARD_MGPOS_CACHE, 13, analyzerFileCallback);
		analyzer.start();

		// processor
		processor = new FolderMonitor(Constant.SDCARD_IN_BOX, 18, processorFileCallback);
		processor.start();

		// transporter
		transporter = new FolderMonitor(Constant.SDCARD_OUT_BOX, 25, transporterCallback);
		transporter.start();

		// mInventoryMonitor = new FolderMonitor(Constant.SDCARD_INV_FOLDER, 20,
		// invFileChanged);
		// mInventoryMonitor.start();

		mRemoteRptSvr = new RemoteReportServer();
		mRemoteRptSvr.start(Constant.CMM_RPT_PORT);
		
		new FileClinetTask().execute();

	}

	private void InitFolder() {
		String inbox = Constant.SDCARD_IN_BOX;
		String outbox = Constant.SDCARD_OUT_BOX;
		String issueBox = Constant.SDCARD_ISSUE_BOX;
		String mgposCache = Constant.SDCARD_MGPOS_CACHE;
		String mgposLog = Constant.SDCARD_LOG_FOLDER;

		File folder = new File(inbox);
		if (!folder.exists()) {
			folder.mkdirs();
			Log.i("LogDemo", "mkdir inbox folder ...");
		}

		folder = new File(outbox);
		if (!folder.exists()) {
			folder.mkdirs();
			Log.i("LogDemo", "mkdir outbox folder ...");
		}

		folder = new File(issueBox);
		if (!folder.exists()) {
			folder.mkdirs();
			Log.i("LogDemo", "mkdir issueBox folder ...");
		}

		folder = new File(mgposCache);
		if (!folder.exists()) {
			folder.mkdirs();
			Log.i("LogDemo", "mkdir mgpos cache folder ...");
		}

		folder = new File(mgposLog);
		if (!folder.exists()) {
			folder.mkdirs();
			Log.i("LogDemo", "mkdir mgpos log folder ...");

			try {

				File newfile = new File("" + Constant.SDCARD_LOG_FOLDER + Constant.LOG_FILE_NAME);
				if (!newfile.isDirectory() && !newfile.exists()) {
					newfile.createNewFile();
				}
			} catch (Exception e) {
				// TODO: handle exception
			}
		}

	}

	private ServiceBroadcastReceiver receiver;
	private String mPosDBPath;
	private MQConnection mInvConn;
	public String mMacAddress = "";
//	private String mLocalIpAddress = "";

	// private ItemService dbitemSvr = null;

	public void onCreate() {
		Log.d(TAG, "============> MGService.onCreate");
		// showNotification();
		super.onCreate();
	}

	public void onStart(Intent intent, int startId) {
		System.out.println("...............................");
		if (!isRunning) {

			InitFolder();

			init();

			doTaskJob();

			Log.i(TAG, "============> MGService.onStart");
			// objHandler.postDelayed(mTasks, 1000);

			regBroadcastReceiver();

			isRunning = true;
		}

		super.onStart(intent, startId);
	}

	private void init() {

		try {
			logHandler = new java.util.logging.FileHandler("" + Constant.SDCARD_LOG_FOLDER + Constant.LOG_FILE_NAME);
			logger.addHandler(logHandler);
			SimpleFormatter formatter = new SimpleFormatter();
			logHandler.setFormatter(formatter);
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		// try {
		// sharedContext = this.createPackageContext(Constant.DB_PACKAGE_NAME,
		// Context.CONTEXT_IGNORE_SECURITY);
		// if (sharedContext == null) {
		// return;
		// }
		// } catch (Exception e) {
		// String error = e.getMessage();
		// return;
		// }

//		mLocalIpAddress  = ServiceUtil.getLocalIpAddress();
		sharedContext = Constant.getShareContext(this);
		mMacAddress  = ServiceUtil.getMacAddress(sharedContext);
		mPosDBPath = sharedContext.getDatabasePath(Constant.POS_DB_PKG_NAME).getAbsolutePath();

		//mInvDBPath = mContextManager.getDbPath(this, Constant.INV_DB_PACKAGE_NAME, Constant.INV_DATABASE_NAME);
		//System.err.println("path ===> " + mInvDBPath);

		//mInvConn = new MQConnection();
		//mInvConn.open(mInvDBPath);

		mgposTool.opendb(mPosDBPath);
		//mgposTool.setMacAddress(mMacAddress);

	}

	public IBinder onBind(Intent intent) {
		Log.i(TAG, "============> MGService.onBind");
		return null;
	}

	public class LocalBinder extends Binder {
		public TransporterService getService() {
			return TransporterService.this;
		}
	}

	public boolean onUnbind(Intent intent) {
		Log.i(TAG, "============> MGService.onUnbind");
		return false;
	}

	public void onRebind(Intent intent) {
		Log.i(TAG, "============> MGService.onRebind");
	}

	public void onDestroy() {

		if (isRunning) {
			unregisterReceiver(receiver);

			if (mRemoteRptSvr != null) {
				mRemoteRptSvr.release();
			}

			if (networkMonitor != null) {
				networkMonitor.release();
			}

			if (mReportService != null) {
				mReportService.release();
			}

			if (transporter != null)
				transporter.release();

			if (analyzer != null)
				analyzer.release();

			if (processor != null)
				processor.release();

			if (filehandler != null)
				filehandler.release();

			// if (mInventoryMonitor != null)
			// mInventoryMonitor.release();

			Log.i(TAG, "============> MGService.onDestroy");

			isRunning = false;
		}
		super.onDestroy();

	}

	private void regBroadcastReceiver() {
		receiver = new ServiceBroadcastReceiver();
		IntentFilter filter = new IntentFilter();
		filter.addAction(Constant.startServiceAction);
		filter.addAction(Constant.stopServiceAction);
		registerReceiver(receiver, filter);
	}

	private class ServiceBroadcastReceiver extends BroadcastReceiver {

		private static final String TAG = "ServiceBroadcastReceiver";

		@Override
		public void onReceive(Context context, Intent intent) {

			if (intent.getAction().equals(Constant.startServiceAction)) {
				Log.i(TAG, "start service ...");
				Intent i = new Intent(context, TransporterService.class);
				context.startService(i);

			} else if (intent.getAction().equals(Constant.stopServiceAction)) {

				Log.i(TAG, "stop service ...");
				Intent i = new Intent(context, TransporterService.class);
				context.stopService(i);
			}
		}
	}

}